﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Diagnostics;

namespace LowLevelGraphics.ColorSpaces
{
    /// <summary>
    /// CMY Color Space
    /// </summary>
    [DebuggerDisplay("C: {m_C}, M: {m_M}, Y: {m_Y}")]
    public class CMY : XYZ
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CMY"/> class.
        /// </summary>
        /// <param name="_color"></param>
        public CMY(Color _color)
            : base(_color)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CMY"/> class.
        /// </summary>
        /// <param name="_C">The _ C.</param>
        /// <param name="_M">The _ M.</param>
        /// <param name="_Y">The _ Y.</param>
        public CMY(int _C, int _M, int _Y)
            :base(_C, _M, _Y)
        {

        }
        /// <summary>
        /// Performs an explicit conversion from <see cref="System.Drawing.Color"/> to <see cref="LowLevelGraphics.ColorSpaces.CMY"/>.
        /// </summary>
        /// <param name="_color">The _color.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator CMY(Color _color)
        {
            return new CMY(_color);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public enum XYZChannel
    {
        /// <summary>
        /// 
        /// </summary>
        X = 0,
        /// <summary>
        /// 
        /// </summary>
        Y = 1,
        /// <summary>
        /// 
        /// </summary>
        Z = 2
    }

    /// <summary>
    /// Class to convert RGB Colors to CMY and back
    /// </summary>
    [DebuggerDisplay("C: {m_C}, M: {m_M}, Y: {m_Y}")]
    public class XYZ : AbstractColorSpace
    {
        protected int m_C = 0;
        protected int m_M = 0;
        protected int m_Y = 0;

        /// <summary>
        /// Primary constructor
        /// </summary>
        /// <param name="_color"></param>
        public XYZ(Color _color)
            : base(_color)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="XYZ"/> class.
        /// </summary>
        /// <param name="_C">The _ C.</param>
        /// <param name="_M">The _ M.</param>
        /// <param name="_Y">The _ Y.</param>
        public XYZ(int _C, int _M, int _Y)
        {
            m_C = _C;
            m_M = _M;
            m_Y = _Y;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_ciexyz"></param>
        internal XYZ(XYZ _ciexyz)
        {
            this.m_Color = _ciexyz.m_Color;
            this.m_C = _ciexyz.m_C;
            this.m_M = _ciexyz.m_M;
            this.m_Y = _ciexyz.m_Y;
        }

        /// <summary>
        /// Performs an explicit conversion from <see cref="System.Drawing.Color"/> to <see cref="LowLevelGraphics.ColorSpaces.XYZ"/>.
        /// </summary>
        /// <param name="_color">The _color.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator XYZ(Color _color)
        {
            return new XYZ(_color);
        }

        /// <summary>
        /// Gets or sets C
        /// </summary>
        public int C
        {
            get { return m_C; }
            set { m_C = value; }
        }

        /// <summary>
        /// Gets or sets M
        /// </summary>
        public int M
        {
            get { return m_M; }
            set { m_M = value; }
        }

        /// <summary>
        /// Gets or sets Y
        /// </summary>
        public int Y
        {
            get { return m_Y; }
            set { m_Y = value; }
        }

        /// <summary>
        /// convert into this color space
        /// </summary>
        protected override void CalcValues()
        {
            m_C = 1 - m_Color.R;
            m_M = 1 - m_Color.G;
            m_Y = 1 - m_Color.B;
        }

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public override AbstractColorSpace Normalize()
        {
            return null;
        }

        /// <summary>
        /// retransform back to rgb color space
        /// </summary>
        /// <returns></returns>
        public override Color ToColor()
        {
            int nR = 1 + m_Color.R;
            int nG = 1 + m_Color.G;
            int nB = 1 + m_Color.B;
            if (nR < 0) nR = 0; if (nR > 255) nR = 255;
            if (nG < 0) nG = 0; if (nG > 255) nG = 255;
            if (nB < 0) nB = 0; if (nB > 255) nB = 255;
            return Color.FromArgb(nR, nG, nB);
        }

        /// <summary>
        /// Gets the values.
        /// </summary>
        /// <returns></returns>
        public override object[] GetValues()
        {
            return new object[] { m_C, m_M, m_Y };
        }

        /// <summary>
        /// Sets the values.
        /// </summary>
        /// <param name="_aObject">The _a object.</param>
        public override void SetValues(object[] _aObject)
        {
            this.m_C = (int)_aObject[0];
            this.m_M = (int)_aObject[1];
            this.m_Y = (int)_aObject[2];
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new XYZ(this);
        }
    }
}
